package com.lwc.cfdns.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lwc.cfdns.common.Assert;
import com.lwc.cfdns.constants.Constants;
import com.lwc.cfdns.enums.ResultCode;
import com.lwc.cfdns.enums.StatusEnum;
import com.lwc.cfdns.exception.BadException;
import com.lwc.cfdns.pojo.bo.system.ConfigBO;
import com.lwc.cfdns.pojo.dto.system.ConfigDTO;
import com.lwc.cfdns.pojo.dto.system.ConfigSetValueDTO;
import com.lwc.cfdns.pojo.entity.SystemCate;
import com.lwc.cfdns.pojo.entity.SystemConfig;
import com.lwc.cfdns.pojo.vo.system.CateVO;
import com.lwc.cfdns.pojo.vo.system.ConfigVO;
import com.lwc.cfdns.service.SystemConfigService;
import com.lwc.cfdns.mapper.SystemConfigMapper;
import com.lwc.cfdns.utils.ConvertUtils;
import com.lwc.cfdns.utils.RedisUtils;
import com.lwc.cfdns.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author spring
 * @description 针对表【cfdns_system_config(系统配置表)】的数据库操作Service实现
 * @createDate 2023-06-01 09:22:52
 */
@Service
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfig>
        implements SystemConfigService {

    @Resource
    private RedisUtils redisUtils;

    /**
     * 创建
     *
     * @param configDTO
     * @return Map<String, Object>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 09:55:20
     */
    @Override
    public Map<String, Object> create(ConfigDTO configDTO) {
        Long count = this.baseMapper.selectCount(new LambdaQueryWrapper<SystemConfig>().eq(SystemConfig::getEnName, configDTO.getEnName()));
        if (count > 0) {
            throw new BadException("配置键名已存在!");
        }
        SystemConfig systemConfig = new SystemConfig();
        BeanUtils.copyProperties(configDTO, systemConfig);
        this.baseMapper.insert(systemConfig);
        // 刷缓存
        viewByEnNameOfCache(systemConfig.getEnName(), true);
        Map<String, Object> map = new HashMap<>();
        map.put("id", systemConfig.getId());
        return map;
    }

    /**
     * 修改
     *
     * @param configDTO
     * @return Map<String, Object>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 09:55:34
     */
    @Override
    public Map<String, Object> update(ConfigDTO configDTO) {
        HashMap<String, Object> map = new HashMap<>();
        SystemConfig systemConfig = this.baseMapper.selectById(configDTO.getId());
        Assert.notNull(systemConfig, ResultCode.NOT_DATA_FOUNT);
        BeanUtils.copyProperties(configDTO, systemConfig, "created_at");
        int i = this.baseMapper.updateById(systemConfig);
        // 刷缓存
        viewByEnNameOfCache(systemConfig.getEnName(), true);
        map.put("result", i);
        return map;
    }

    /**
     * 详情
     *
     * @param id
     * @return ConfigVO
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 09:55:54
     */
    @Override
    public ConfigVO view(Long id) {
        SystemConfig systemConfig = this.baseMapper.selectById(id);
        Assert.notNull(systemConfig, ResultCode.NOT_DATA_FOUNT);
        ConfigVO configVO = new ConfigVO();
        BeanUtils.copyProperties(systemConfig, configVO);
        // 处理rule
        getRuleToList(configVO);
        return configVO;
    }

    /**
     * 格式化规则转成list
     *
     * @param configVO
     * @return void
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 17:46:09
     */
    private void getRuleToList(ConfigVO configVO) {
        // 处理rule
        String[] arr = {"select", "radio", "checkbox"};
        if (StringUtils.isNotEmpty(configVO.getRule()) && Arrays.asList(arr).contains(configVO.getKeyType())) {
            String[] strings = ConvertUtils.toStrArray("\\n", configVO.getRule());
            System.out.println(strings);
            ArrayList<Map<String, Object>> ruleArr = new ArrayList<>();
            for (String s : strings) {
                Map<String, Object> map = new HashMap<>();
                String[] strings1 = ConvertUtils.toStrArray(":", s);
                map.put("value", strings1[0]);
                map.put("label", strings1[1]);
                ruleArr.add(map);
                if (configVO.getValue().equals(strings1[0])) {
                    configVO.setValueTxt(strings1[1]);
                }
            }
            configVO.setRuleArr(ruleArr);
        } else {
            configVO.setValueTxt(configVO.getValue());
        }
    }

    /**
     * 删除
     *
     * @param ids
     * @return Map<String, Object>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 09:56:11
     */
    @Override
    public Map<String, Object> delete(String ids) {
        int i = 0;
        if (ids.contains(",")) {
            i = this.baseMapper.delete(new LambdaQueryWrapper<SystemConfig>().in(SystemConfig::getId, ConvertUtils.toLongArray(ids)));
        } else {
            i = this.baseMapper.deleteById(ConvertUtils.toLong(ids));
        }
        // 有可能删除多个，直接全刷
        refreshCache();
        Map<String, Object> map = new HashMap<>();
        map.put("result", i);
        return map;
    }

    /**
     * 列表
     *
     * @param configBO
     * @return IPage<SystemConfig>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 09:57:09
     */
    @Override
    public IPage<SystemConfig> lists(ConfigBO configBO) {
        Page<SystemConfig> page = this.baseMapper.selectPage(configBO.toPage(), configBO.toQueryWrapper());

        //转化为VO
        page.convert(s -> {
            ConfigVO configVO = new ConfigVO();
            BeanUtils.copyProperties(s, configVO);
            // 处理rule
            getRuleToList(configVO);
            return configVO;
        });

        return page;
    }

    /**
     * 刷新缓存
     *
     * @param enName
     * @return Map<String, Object>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/5/29 15:48:33
     */
    @Override
    public Map<String, Object> refreshCache(String enName) {
        Boolean res = redisUtils.del(Constants.configPrefix + enName);
        Map<String, Object> map = new HashMap<>();
        map.put("result", res ? 1 : 0);
        return map;
    }

    /**
     * 清除缓存(全部)
     *
     * @return Map<String, Object>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 11:54:48
     */
    @Override
    public Map<String, Object> refreshCache() {
        List<Object> systemConfigs = this.baseMapper.selectObjs(new LambdaQueryWrapper<SystemConfig>().select(SystemConfig::getEnName));
        List<Object> keys = new ArrayList<>();
        for (Object enName : systemConfigs) {
            // 增加前缀
            keys.add(Constants.configPrefix + enName);
        }
        Long res = redisUtils.del(keys);
        Map<String, Object> map = new HashMap<>();
        map.put("result", res);
        return map;
    }

    /**
     * 配置键名
     *
     * @param enName
     * @return ConfigVO
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 13:43:27
     */
    @Override
    public ConfigVO viewByEnNameOfCache(String enName) {
        return viewByEnNameOfCache(enName, false);
    }

    /**
     * 配置键名
     *
     * @param enName 键名
     * @param force  强制刷缓存
     * @return ConfigVO
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 13:44:32
     */
    @Override
    public ConfigVO viewByEnNameOfCache(String enName, Boolean force) {
        ConfigVO configVO = null;
        if (!redisUtils.hasKey(Constants.configPrefix + enName) || force == true) {
            SystemConfig systemConfig = this.baseMapper.selectOne(new LambdaQueryWrapper<SystemConfig>().eq(SystemConfig::getEnName, enName).eq(SystemConfig::getStatus, StatusEnum.NORMAL.getCode()));
            Assert.notNull(systemConfig, ResultCode.NOT_DATA_FOUNT);
            configVO = new ConfigVO();
            BeanUtils.copyProperties(systemConfig, configVO);
            redisUtils.set(Constants.configPrefix + enName, configVO);
        } else {
            configVO = (ConfigVO) redisUtils.get(Constants.configPrefix + enName);
        }
        return configVO;
    }

    /**
     * 更新值
     *
     * @param configSetValueDTO
     * @return Map<String, Object>
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/6/1 17:34:29
     */
    @Override
    public Map<String, Object> setValue(ConfigSetValueDTO configSetValueDTO) {
        SystemConfig systemConfig = this.baseMapper.selectById(configSetValueDTO.getId());
        Assert.notNull(systemConfig, ResultCode.NOT_DATA_FOUNT);
        LambdaUpdateWrapper<SystemConfig> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(SystemConfig::getId, configSetValueDTO.getId()).set(SystemConfig::getValue, configSetValueDTO.getValue());
        int res = this.baseMapper.update(null, lambdaUpdateWrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("result", res);
        return map;
    }
}